package main

import (
	"fmt"
	"net/http"
	"os"

	"saysay/config"
	"saysay/handlers"
	"saysay/models"
	"saysay/routes"
	"saysay/utils"

	"github.com/gin-gonic/gin"
	_ "github.com/mattn/go-sqlite3"
)

func main() {
	// 加载配置
	cfg := config.LoadConfig()

	// 验证配置
	if err := cfg.Validate(); err != nil {
		fmt.Printf("配置错误: %v\n", err)
		os.Exit(1)
	}

	// 初始化日志系统
	if err := utils.InitLogger(); err != nil {
		fmt.Printf("日志系统初始化失败: %v\n", err)
		os.Exit(1)
	}

	utils.Info("应用启动中...")
	cfg.Print()

	// 初始化数据库
	db, err := models.InitDB()
	if err != nil {
		utils.Error("数据库初始化失败: %v", err)
		os.Exit(1)
	}
	defer db.Close()
	utils.Info("数据库初始化成功")

	// 初始化处理器
	handlers.InitHandlers(db)
	utils.Info("处理器初始化成功")

	// 创建 Gin 引擎
	router := gin.Default()

	// 添加恢复中间件（必须在最前面）
	router.Use(recoveryMiddleware())

	// 添加日志中间件
	router.Use(loggingMiddleware())

	// 加载 HTML 模板
	router.LoadHTMLGlob("templates/*")

	// 配置静态文件服务
	router.Static("/static", "./static")

	// 配置路由
	routes.SetupRoutes(router, cfg.SecretKey)
	utils.Info("路由配置完成")

	// 启动服务器
	listenAddr := cfg.GetAddr()
	utils.Info("服务器启动在 http://localhost%s", listenAddr)
	fmt.Printf("\n服务器启动在 http://localhost%s\n", listenAddr)
	fmt.Println("使用 Ctrl+C 停止服务器\n")

	if err := http.ListenAndServe(listenAddr, router); err != nil {
		utils.Error("服务器启动失败: %v", err)
		os.Exit(1)
	}
}

// loggingMiddleware 日志中间件
func loggingMiddleware() gin.HandlerFunc {
	return gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
		logMessage := fmt.Sprintf("[%s] %s %s %s %d %s %s",
			param.TimeStamp.Format("2006-01-02 15:04:05"),
			param.ClientIP,
			param.Method,
			param.Path,
			param.StatusCode,
			param.Latency,
			param.ErrorMessage,
		)

		if param.StatusCode >= 500 {
			utils.Error("%s", logMessage)
			if param.ErrorMessage != "" {
				utils.Error("错误详情: %s", param.ErrorMessage)
			}
		} else if param.StatusCode >= 400 {
			utils.Debug("%s", logMessage)
		} else {
			utils.Info("%s", logMessage)
		}

		return "" // 返回空字符串，因为我们自己处理日志
	})
}

// recoveryMiddleware 恢复中间件
func recoveryMiddleware() gin.HandlerFunc {
	return gin.CustomRecoveryWithWriter(nil, func(c *gin.Context, recovered interface{}) {
		errMsg := fmt.Sprintf("Panic recovered: %v", recovered)

		// 输出到stderr，确保能看到
		fmt.Fprintf(os.Stderr, "PANIC: %s at URL: %s\n", errMsg, c.Request.URL.String())
		utils.Error("%s, URL: %s", errMsg, c.Request.URL.String())

		// 返回JSON而不是HTML，避免再次panic
		c.JSON(http.StatusInternalServerError, gin.H{
			"error":   "系统错误，请稍后重试",
			"details": errMsg,
		})
		c.AbortWithStatus(http.StatusInternalServerError)
	})
}
